package com.norriekoelle.virtualsensors.client;

import java.util.Date;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Typeface;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Vibrator;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;

import com.norriekoelle.virtualsensors.R;
import com.norriekoelle.virtualsensors.server.CommandInterface;
import com.norriekoelle.virtualsensors.shared.LogToFile;

/**
 * Application for running the client, logging accelerometer data 
 * and displaying content on screen.
 * 
 * @author Lauren Norrie (norrielm)
 */
// TODO(norrielm): Remove this class if we're only using the Bookshelf one.
public class HotspotActivity extends ClientActivity implements SensorEventListener {
	private static final String LOG = "HotspotActivity";
	private LogToFile log;	
	public static boolean doLog = false;
	//Sensors
	private SensorManager sensorMgr = null;
	private long lastTime = -1;
	private float[] gravity = new float[3];
	private float[] linear_acceleration = new float[3];
	private String chosenApp = null;
	private int openAppId;
		
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.hotspots);
        handleMessage("starting...");   

        connectionManager.start();
        
        // Buttons
        Button b = (Button) findViewById(R.id.hotButton);
        b.setOnClickListener(new OnClickListener(){
			@Override public void onClick(View arg0) {				
				loadCreateDialog();				
			}
        });
        
        b = (Button) findViewById(R.id.logButton);
        b.setOnClickListener(new OnClickListener(){
			@Override public void onClick(View arg0) {
				connectionManager.sendUDPMessage("", "log");
				
				if(log == null){
					log = new LogToFile("Exp-" + DateFormat.format("hhmmss", new Date()));
				} else {
					synchronized(log){ 
						log.close();
						log = new LogToFile("Exp-" + DateFormat.format("hhmmss", new Date()));
					}
				}
				handleMessage("New logfile created.");
				
				// TODO(norrielm): Pull tactile notifications into a helper method.
				Vibrator v = (Vibrator) getSystemService(VIBRATOR_SERVICE);
				v.vibrate(75);
			}
        });
    } 
    
    /**
     * Create and display a dialog that allows the user to select the type of hotspot they wish to create.
     */
    // TODO(norrielm): Could pull these dialogs out into a helper class.
    public void loadCreateDialog(){
    	final CharSequence[] apps = {"Photos", "Camera", "Books", "Text..."};
    	chosenApp = null;
    	
		AlertDialog.Builder d = new AlertDialog.Builder(this);
		d.setSingleChoiceItems(apps, -1, new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog,
					int id) {
				chosenApp = apps[id].toString();
			}
		});
		
		d.setTitle("Create hotspot here")
		.setCancelable(true)
		.setPositiveButton("OK", 
		new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog,
					int id) {
				if(chosenApp.toLowerCase().equals("text...")){
					loadTextDialog();
				}else{
					createHotspot(chosenApp);
				}
				dialog.cancel();
			}
		})
		.setNeutralButton("Cancel", 
				new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog,
							int id) {
						dialog.cancel();
					}
				});
		d.create();
		d.show();
    }
    
    public void loadTextDialog(){
    	final Dialog d = new Dialog(this);
		d.setContentView(R.layout.edit_text);
    	d.setTitle("Add message hotspot");
		
		Button b = (Button)d.findViewById(R.id.okbutton);
		b.setOnClickListener(new OnClickListener(){
			@Override
			public void onClick(View arg0) {
				EditText e = (EditText)d.findViewById(R.id.tagBox);
				String text = e.getText().toString().trim();
				
				createHotspot(text);
				d.cancel();
			}
        });
		b = (Button)d.findViewById(R.id.cancelbutton);
		b.setOnClickListener(new OnClickListener(){
			@Override
			public void onClick(View arg0) {
				d.cancel();
			}
        });
		d.show();
    }
    
    public void createHotspot(String text){ 
    	if (text == null) {
    		Log.w(LOG, "Trying to create a hotspot with null string");
    		return;
    	}
    	connectionManager.sendUDPMessage("", ("Hotspot " + text));
		
    	// Register the hotspot with the server.
		handleMessage("hotspot added : " + text);
		Vibrator v = (Vibrator) getSystemService(VIBRATOR_SERVICE);
		v.vibrate(75);
		
		// Display a tag in the UI.
		TextView tag = (TextView)findViewById(R.id.hotText);
		Typeface font = Typeface.createFromAsset(getAssets(), "upcll.ttf");
		tag.setTypeface(font);
		tag.setText(text + " added");	
    }
    
    @Override
	public void onAccuracyChanged(Sensor sensor, int accuracy) {
    	// Unused.
	}
    
	public void onSensorChanged(SensorEvent event){		
		
		if (doLog && event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
			 long currTime = System.currentTimeMillis();
			 
			 if ((currTime - lastTime) >= 49) {
				 lastTime = currTime;
				 final float alpha = 0.8f;
		
		         //remove gravity to get linear acceleration
		         gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0];
		         gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1];
		         gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2];
		
		         linear_acceleration[0] = event.values[0] - gravity[0];
		         linear_acceleration[1] = event.values[1] - gravity[1];
		         linear_acceleration[2] = event.values[2] - gravity[2];
		         
		         // TODO(norrielm): Should have a better check on when to log than to see if it's 
		         // not null.
		         if (log != null) {
		        	 log.write(String.format(System.currentTimeMillis() + " %f %f %f", 
						linear_acceleration[0], linear_acceleration[1], linear_acceleration[2]));
		         }
			 }
		}
	}
    
	/**
	 * Register the listener onResume
	 */
	@Override
	public void onResume(){
		super.onResume();
		// TODO(norrielm): Check if we are using this here.
		if (sensorMgr == null) {
			// Register accelerometer for scrolling interaction. 
			sensorMgr = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
			Sensor accel = sensorMgr.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);			
			boolean accelSupported = sensorMgr.registerListener(this, accel,
				SensorManager.SENSOR_DELAY_FASTEST);
			if (!accelSupported) {
				Log.d(LOG, "TYPE_ACCELEROMETER not supported...");
				sensorMgr.unregisterListener(this, accel);
			}
		}
	}
	
	/**
	 * Stop receive loop, close logs, tell server we're closing the connection 
	 */
	@Override 
	public void finish(){
		handleMessage("closing...");
		
		if (log != null) {
			log.close();
			sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, 
				Uri.parse("file://" + Environment.getExternalStorageDirectory())));	
		}
		connectionManager.closeServer();
		super.finish();
	}

	@Override
	public void handleCommand(String command) {
		Log.d(LOG, command);
		CommandInterface.commands c = CommandInterface.handleKinectMessage(command);
		
		switch(c) {
		case TRACKING_ON:			
				//start logging accel
				//AndroidClient.doLog = true;
//				activity.runOnUiThread(new Runnable(){
//					@Override
//					public void run() {
//					 	Button b= (Button)activity.findViewById(R.id.hotButton);
//					 	b.setEnabled(true);
//					 	b.setClickable(true);
//					}
//				 });
				break;
		case TRACKING_OFF:
				//stop logging accel
				//AndroidClient.doLog = false; 
				/* 
				 * Disable the hotspot button
				 * context.runOnUiThread(new Runnable(){
					@Override
					public void run() {
					 	Button b= (Button)context.findViewById(R.id.hotButton);
					 	b.setEnabled(false);
					 	b.setClickable(false);
					}
				 });*/
			
				break;
		/*case NEW_USER:
				//parse ID
				String num = serverMessage.substring(serverMessage.indexOf("user ")+5,
													 serverMessage.indexOf("user ")+6);
				int got_userid = Integer.valueOf(num);
	
				//New: assigned id
				if(serverMessage.toLowerCase().contains("new")){
					userID = got_userid;				
					/* Update on screen
					 * context.runOnUiThread(new Runnable(){
						public void run() {
							TextView idView = (TextView)context.findViewById(R.id.clientID);
							idView.setText(ID +" : User " + userID);
						}
					});*
				}	
				break;
		case LOST_USER:
				num = serverMessage.substring(serverMessage.indexOf("user ")+5,
						 serverMessage.indexOf("user ")+6);
				got_userid = Integer.valueOf(num);
				
				if(userID == got_userid){
					userID = -1;
					/*Update on screen
					 * context.runOnUiThread(new Runnable(){
						@Override
						public void run() {
							//TextView idView = (TextView)context.findViewById(R.id.clientID);
							//idView.setText(ID +" : (lost user)");
						}
					 });
				}
				break;*/
		case LOG_ON:
				doLog(false);
				break;
		case LOG_OFF:
				handleMessage("Log off");
				doLog(false);
				break;
		}
	}

    public void doLog(boolean isLogOn){
    	if (isLogOn){
    		if (log != null) {
    			Log.w(LOG, "Closing open logfile.");	
    			log.close();
    		}
    		log = new LogToFile("Accel-" + System.currentTimeMillis());
    		// Tell the media scanner about the new file so that it is
            // immediately available to the user if mounted as an external hard drive.
			sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, 
				Uri.parse("file://" + Environment.getExternalStorageDirectory())));
    		Log.d(LOG, "New logfile created");
    	}
    	doLog = isLogOn;
    }
    
    /**
     * Log message and display status on screen
     * @param message
     */
    public void handleMessage(String message){
    	Log.d(LOG, message);
    	
//    	TextView statusView = (TextView)this.findViewById(R.id.status);
//    	statusView.setText(message);     	
    }
    	
	@Override
	public void exit() {
		TextView hid = (TextView) findViewById(R.id.hotID);
		TextView tag = (TextView) findViewById(R.id.hotText);
		Typeface font = Typeface.createFromAsset(getAssets(), "upcll.ttf");
		tag.setTypeface(font);
		hid.setTypeface(font);
		hid.setText("");
		tag.setText("None here!");
		// TODO(norrielm): Handle the dialog properly.
//		if (dialogOpen)
//			d = null;

		// TODO(norrielm): Create a state for these buttons
		Button bh = (Button) findViewById(R.id.hotButton);
		Button bi = (Button) findViewById(R.id.launcher);
		bi.setVisibility(Button.INVISIBLE);
		bh.setVisibility(Button.VISIBLE);
		
		// TODO(norrielm): create a method for this.
		if (openAppId != -1){
			finishActivity(openAppId);
			openAppId = -1;							
		}		
	}

	@Override
	public void handleDisconnect() {
		ImageView logo = (ImageView) findViewById(R.id.logo);
		logo.setImageDrawable(getResources().getDrawable(R.drawable.logo_disconnected));
	}
}
